package com.jdd.modules.parkmonthly.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jdd.common.api.vo.Result;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.system.vo.LoginUser;
import com.jdd.common.util.DateUtil;
import com.jdd.common.util.LoginUserUtils;
import com.jdd.common.util.SnowFlakeUtil;
import com.jdd.modules.parkcar.entity.ParkCarMonthly;
import com.jdd.modules.parkcar.entity.ParkSpace;
import com.jdd.modules.parkcar.service.IParkCarMonthlyService;
import com.jdd.modules.parkcar.service.IParkSpaceService;
import com.jdd.modules.parking.entity.ConfigParkInfo;
import com.jdd.modules.parking.entity.ParkCarEnterLog;
import com.jdd.modules.parking.service.IConfigParkInfoService;
import com.jdd.modules.parking.service.IparkCarEnterLogService;
import com.jdd.modules.parkmonthly.entity.MonthlyCarTypeConvert;
import com.jdd.modules.parkmonthly.entity.MonthlyCardInfo;
import com.jdd.modules.parkmonthly.entity.MonthlyPackageInfo;
import com.jdd.modules.parkmonthly.service.IAddMonthlyCardInfoService;
import com.jdd.modules.parkmonthly.service.IMonthlyCarTypeConvertService;
import com.jdd.modules.parkmonthly.service.IMonthlyCardInfoService;
import com.jdd.modules.parkmonthly.service.IMonthlyPackageInfoService;
import com.jdd.modules.sdkidentifyresultpushlog.entity.vo.ParkCarEnterLogSyncV3Vo;
import com.jdd.modules.sdkidentifyresultpushlog.service.ISdkIdentifyResultPushLogV3Service;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 月卡新增
 * @Author: qilina
 * @Date:   2022-1-7
 * @Version: V2.0
 */
@Service
@Slf4j
public class AddMonthlyCardInfoServiceImpl implements IAddMonthlyCardInfoService {

    @Resource
    private IMonthlyCarTypeConvertService iMonthlyCarTypeConvertService;
    @Resource
    private IMonthlyPackageInfoService iMonthlyPackageInfoService;
    @Resource
    private IparkCarEnterLogService iparkCarEnterLogService;
    @Resource
    private IParkCarMonthlyService iParkCarMonthlyService;
    @Resource
    private IMonthlyCardInfoService iMonthlyCardInfoService;
    @Resource
    private IParkSpaceService parkSpaceService;
    @Resource
    private IConfigParkInfoService configParkInfoService;
    @Resource
    private ISdkIdentifyResultPushLogV3Service sdkIdentifyResultPushLogV3Service;



    /**
     * 添加月卡
     *
     * @param monthlyCardInfo
     * @return
     */
    @Override
    @CacheEvict(value = {"monthly:cardAndPackage"}, allEntries = true)
    public Result<MonthlyCardInfo> add(MonthlyCardInfo monthlyCardInfo) {

        log.info("新增月卡信息，传入的参数------------------------》:{}", monthlyCardInfo);
        // 获取车位车牌，车位
        List<String> plateNoList = monthlyCardInfo.getPlateNoList();
        List<String> spaces = monthlyCardInfo.getParkNumberList();
        ConfigParkInfo oneByParkCode = configParkInfoService.findConfigParkInfoByParkCode();

        boolean addMonthly = true;
        // 1.新增月卡
        addMonthly = iMonthlyCardInfoService.getMonthlyCardInfo(monthlyCardInfo,oneByParkCode);
        if (!addMonthly) {
            return Result.error("新增月卡信息失败！");
        }
        // 2.获取车位信息，更新车位，不更新费用
        List<ParkSpace> parkSpaces = dealParkSpace(spaces,monthlyCardInfo);
        addMonthly = parkSpaceService.updateBatchById(parkSpaces);
        if (!addMonthly) {
            return Result.error("新增月卡信息失败！");
        }
        log.info("新增月卡绑定的车位信息为------------------------>:{}", parkSpaces);
        // 3.新增月卡操作记录
        addMonthly = iMonthlyCardInfoService.getMonthlyCardEditInfo(monthlyCardInfo, JddConstant.StringNumber.STRING_FOUR);
        if (!addMonthly) {
            return Result.error("新增月卡操作记录信息失败！");
        }
        // 新增月租车
        List<ParkCarMonthly> list = iMonthlyCardInfoService.getParkCarMonthlyEntity(parkSpaces, plateNoList, monthlyCardInfo);
        boolean addResult = iParkCarMonthlyService.saveBatch(list);
        if (!addResult) {
            return Result.error("新增月租车信息失败！");
        }
        if (monthlyCardInfo.getEndTime().equals(monthlyCardInfo.getBeginTime())) {
            log.info("月卡未开通具体时间！");
            return Result.ok("开通成功！");
        }
        QueryWrapper<ParkSpace> parkSpaceQueryWrapper = new QueryWrapper<>();
        parkSpaceQueryWrapper.eq("monthly_card_id", monthlyCardInfo.getId());
        parkSpaceQueryWrapper.eq("park_code", monthlyCardInfo.getParkCode());
        parkSpaceQueryWrapper.eq("park_status", 0);
        List<ParkSpace> parkSpaceList = parkSpaceService.list(parkSpaceQueryWrapper);
        if(CollectionUtils.isEmpty(parkSpaceList)){
            log.info("月卡未开通具体时间！");
            return Result.ok("开通成功！");
        }
        MonthlyPackageInfo monthlyPackageInfo = iMonthlyPackageInfoService.getById(monthlyCardInfo.getPackageId());
        List<String> areaList = parkSpaces.stream().map(ParkSpace::getAreaId).distinct().collect(Collectors.toList());
        if(areaList.size()==1){
            // 单区域 一位一车
            if (monthlyPackageInfo.getBindingSpaceNumber()== JddConstant.IntNumber.INT_ONE &&  monthlyPackageInfo.getBindingCarNumber() == JddConstant.IntNumber.INT_ONE ){
                this.oneAreaOneSpaceOneCar(monthlyCardInfo,areaList,parkSpaceList,monthlyPackageInfo);
            }
            // 单区域 一位多车
            if (monthlyPackageInfo.getBindingSpaceNumber()== JddConstant.IntNumber.INT_ONE &&  monthlyPackageInfo.getBindingCarNumber() >JddConstant.IntNumber.INT_ONE ){
                this.oneAreaOneSpaceMoreCar(monthlyCardInfo,areaList,parkSpaceList,monthlyPackageInfo);
            }
            // 单区域 多位多车
            if (monthlyPackageInfo.getBindingSpaceNumber()> JddConstant.IntNumber.INT_ONE &&  monthlyPackageInfo.getBindingCarNumber() >JddConstant.IntNumber.INT_ONE ){
                this.oneAreaMoreSpaceMoreCar(monthlyCardInfo,areaList,parkSpaceList,monthlyPackageInfo);
            }
        }else {
            // 多区域一车
            if (monthlyPackageInfo.getBindingCarNumber() == JddConstant.IntNumber.INT_ONE ){
                this.moreAreaOneCar(monthlyCardInfo,areaList,parkSpaceList,monthlyPackageInfo);
            }
            // 多区域多车
            if (monthlyPackageInfo.getBindingCarNumber() > JddConstant.IntNumber.INT_ONE ){
            }
        }
        return Result.ok("开通成功！");
    }



    /**
     * 新增月卡时，更新车位绑定
     * @param spaces
     * @param monthlyCardInfo
     * @return
     */
    protected List<ParkSpace> dealParkSpace(List<String> spaces,MonthlyCardInfo monthlyCardInfo){
        List<ParkSpace> parkSpaces = new ArrayList<>();
        for (String paces : spaces) {
            ParkSpace parkSpace = parkSpaceService.getById(paces);
            parkSpace.setMonthlyCode(monthlyCardInfo.getMonthlyCode());
            parkSpace.setMonthlyCardId(monthlyCardInfo.getId());
            parkSpace.setUserName(monthlyCardInfo.getCarOwnerName());
            parkSpace.setMobile(monthlyCardInfo.getTelephone());
            parkSpace.setStartTime(monthlyCardInfo.getBeginTime());
            parkSpace.setEndTime(monthlyCardInfo.getEndTime());
            parkSpace.setAddress(monthlyCardInfo.getAddress());
            parkSpace.setStatus("Y");
            LoginUser sysUser = LoginUserUtils.getLoginUser();
            parkSpace.setCreateUser(sysUser.getRealname());
            parkSpaces.add(parkSpace);
        }
        return parkSpaces;
    }

    /**
     * 单区域一位一车
     * @param monthlyCardInfo
     * @param areaList
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */
    public Result oneAreaOneSpaceOneCar(MonthlyCardInfo monthlyCardInfo, List<String> areaList, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo) {
       log.info("=====================开通单区域一位一车=====================");
        List<String> plateNoList =  monthlyCardInfo.getPlateNoList();
        // 查询入场记录
        QueryWrapper<ParkCarEnterLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("park_code",monthlyCardInfo.getParkCode());
        queryWrapper.eq("plate_no",plateNoList.get(0));
        queryWrapper.eq("is_out","0");
        queryWrapper.orderByDesc("car_enter_time");
        List<ParkCarEnterLog> enterLogs = iparkCarEnterLogService.list(queryWrapper);
        if (CollectionUtils.isEmpty(enterLogs)){
            return Result.ok("开通成功");
        }
        // 下次生效，不转卡
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            return Result.ok("开通成功");
        }
        ParkCarEnterLog parkCarEnterLog = new ParkCarEnterLog();
        // 最近一条记录是否在指定区域
        if (enterLogs.get(0).getAreaId().equals(areaList.get(0))){
            BeanUtils.copyProperties(enterLogs.get(0),parkCarEnterLog);
            getTurnAddLog(parkCarEnterLog,monthlyCardInfo,parkSpaceList,monthlyPackageInfo);
        }
        return Result.ok("开通成功");
    }


    /**
     * 单区域一位多车
     * @param monthlyCardInfo
     * @param areaList
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */
    public Result oneAreaOneSpaceMoreCar(MonthlyCardInfo monthlyCardInfo, List<String> areaList, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo) {
        log.info("=====================开通单区域一位多车=====================");
        List<String> plateNoList =  monthlyCardInfo.getPlateNoList();
        // 多车牌最近的入场记录入场记录
        List<ParkCarEnterLog> parkCarEnterLogList = getList(monthlyCardInfo.getParkCode(),plateNoList,areaList.get(0));
        if (CollectionUtils.isEmpty(parkCarEnterLogList)){
            return Result.ok("开通成功");
        }
        // 下次生效，不转卡
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            return Result.ok("开通成功");
        }
        ParkCarEnterLog parkCarEnterLog = new ParkCarEnterLog();
        BeanUtils.copyProperties(parkCarEnterLogList.get(0),parkCarEnterLog);
        getTurnAddLog(parkCarEnterLog,monthlyCardInfo,parkSpaceList,monthlyPackageInfo);
        return Result.ok("开通成功");
    }




    /**
     * 单区域，多位多车
     * @param monthlyCardInfo
     * @param areaList
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */
    public Result oneAreaMoreSpaceMoreCar(MonthlyCardInfo monthlyCardInfo, List<String> areaList, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo) {
        log.info("=====================开通单区域多位多车=====================");
        List<String> plateNoList =  monthlyCardInfo.getPlateNoList();
        // 查询入场记录
        List<ParkCarEnterLog> parkCarEnterLogList = getList(monthlyCardInfo.getParkCode(),plateNoList,areaList.get(0));
        if (CollectionUtils.isEmpty(parkCarEnterLogList)){
            return Result.ok("开通成功");
        }
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            // 下次生效，不转卡
            return Result.ok("开通成功");
        }
        iMonthlyCardInfoService.dealCarLog(parkCarEnterLogList,parkSpaceList,monthlyCardInfo,monthlyPackageInfo);
        return Result.ok("开通成功");
    }




    /**
     * 多区域一车
     * @param monthlyCardInfo
     * @param areaList
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */
    public Result moreAreaOneCar(MonthlyCardInfo monthlyCardInfo, List<String> areaList, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo) {
        log.info("=====================开通多区域一车=====================");
        // 查询入场记录
        QueryWrapper<ParkCarEnterLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("park_code",monthlyCardInfo.getParkCode());
        queryWrapper.eq("is_out","0");
        queryWrapper.eq("plate_no",monthlyCardInfo.getPlateNoList().get(0));
        queryWrapper.orderByDesc("car_enter_time");
        List<ParkCarEnterLog> enterLogs = iparkCarEnterLogService.list(queryWrapper);
        if(CollectionUtils.isEmpty(enterLogs)){
            return Result.ok("开通成功");
        }
        if (!areaList.contains(enterLogs.get(0).getAreaId())){
            return Result.ok("开通成功");
        }
        if (JddConstant.IntNumber.INT_TWO == monthlyCardInfo.getIsEffect()) {
            // 下次生效，不转卡
            return Result.ok("开通成功");
        }
        ParkCarEnterLog parkCarEnterLog = new ParkCarEnterLog();
        BeanUtils.copyProperties(enterLogs.get(0),parkCarEnterLog);
        getTurnAddLog(parkCarEnterLog,monthlyCardInfo,parkSpaceList,monthlyPackageInfo);
        return Result.ok("开通成功");
    }

    /**
     * 单区域 一位 新增入场记录
     *
     * @param parkCarEnterLog
     * @param monthlyCardInfo
     * @param parkSpaceList
     * @param monthlyPackageInfo
     */

    private void getTurnAddLog(ParkCarEnterLog parkCarEnterLog, MonthlyCardInfo monthlyCardInfo, List<ParkSpace> parkSpaceList, MonthlyPackageInfo monthlyPackageInfo) {
        // 开过期月租，在场车辆的入场时间在月租结束时间之后，不处理
        if (monthlyCardInfo.getEndTime().before(DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()))) {
            return;
        }

        parkCarEnterLog.setId(SnowFlakeUtil.getId());
        parkCarEnterLog.setParkNumber(parkSpaceList.get(0).getParkNumber());
        parkCarEnterLog.setCarNature("1");
        parkCarEnterLog.setCarTypeId(monthlyPackageInfo.getMonthlyTypeId());
        parkCarEnterLog.setCarTypeName(monthlyPackageInfo.getMonthlyTypeName());
        parkCarEnterLog.setMonthlyCardId(monthlyCardInfo.getId());
        parkCarEnterLog.setCreateTime(new Date());
        parkCarEnterLog.setEnterType(JddConstant.IntNumber.INT_ZERO);
        // 若入场时间在月卡开始之后，新增转卡记录，否则，生成欲转卡记录
        if (DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()).after(monthlyCardInfo.getBeginTime())
                && DateUtil.fomatDateTime(parkCarEnterLog.getCarEnterTime()).before(monthlyCardInfo.getEndTime())) {
            String time = DateUtil.addSecond(parkCarEnterLog.getCarEnterTime(), JddConstant.IntNumber.INT_ONE);
            parkCarEnterLog.setCarEnterTime(time);
            parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_TWO);
        } else {
            parkCarEnterLog.setIsTransfer(JddConstant.StringNumber.STRING_ONE);
            parkCarEnterLog.setCarEnterTime(DateUtil.fomatDateTimeStr(monthlyCardInfo.getBeginTime()));
        }

        // 更新车位信息
        parkSpaceList.get(0).setPlateNo(parkCarEnterLog.getPlateNo());
        parkSpaceList.get(0).setParkStatus("1");
        parkSpaceService.updateById(parkSpaceList.get(0));
        log.info("待插入入场记录---------------->:{}",parkCarEnterLog);
        iparkCarEnterLogService.save(parkCarEnterLog);
        MonthlyCarTypeConvert monthlyCarTypeConvert = iMonthlyCardInfoService.getMonthlyCarTypeConvert(monthlyCardInfo, parkCarEnterLog, monthlyPackageInfo);
        iMonthlyCarTypeConvertService.save(monthlyCarTypeConvert);
        // 月租车入场记录上传到云端
        try {
        	ParkCarEnterLogSyncV3Vo entity = new ParkCarEnterLogSyncV3Vo();
        	entity.setParkCarEnterLogStr(JSON.toJSONString(parkCarEnterLog));
        	entity.setParkStatus(JddConstant.ParkSpace.PARKSTATUS_ONE);
            String url = "";
        	sdkIdentifyResultPushLogV3Service.sendMessageV3(entity,url);
		} catch (IOException e) {
			e.printStackTrace();
		}
    }



    /**
     * 一车多位，单区域下,最近的一条记录
     * @param parkCode
     * @param plateNos
     * @param areaId
     * @return
     */
    private List<ParkCarEnterLog> getList(String parkCode, List<String> plateNos, String areaId) {
        QueryWrapper<ParkCarEnterLog> parkCarEnterLogQueryWrapper = new QueryWrapper<>();
        parkCarEnterLogQueryWrapper.eq("park_code", parkCode);
        parkCarEnterLogQueryWrapper.eq("enter_type", 0);
        parkCarEnterLogQueryWrapper.eq("is_out", JddConstant.StringNumber.STRING_ZERO);
        parkCarEnterLogQueryWrapper.in("plate_no", plateNos);
        parkCarEnterLogQueryWrapper.orderByAsc("car_enter_time");
        List<ParkCarEnterLog> parkCarEnterLogList = iparkCarEnterLogService.list(parkCarEnterLogQueryWrapper);
        log.info("办理月卡延期，是否有在场的信息------------------------------》:{}", parkCarEnterLogList);
        Map<String, ParkCarEnterLog> newMap = new HashMap(16);
        for (ParkCarEnterLog parkCarEnterLog : parkCarEnterLogList) {
            newMap.put(parkCarEnterLog.getPlateNo(), parkCarEnterLog);
        }
        List<ParkCarEnterLog> carEnterLogs = new ArrayList<>();
        for (String key : newMap.keySet()) {
            carEnterLogs.add(newMap.get(key));
        }
        List<ParkCarEnterLog> enterLogList = new ArrayList<>();
        for (ParkCarEnterLog parkCarEnterLog : carEnterLogs) {
            if (areaId.equals(parkCarEnterLog.getAreaId())) {
                enterLogList.add(parkCarEnterLog);
            }
        }
        if (CollectionUtils.isEmpty(enterLogList)){
            return enterLogList;
        }
        List<ParkCarEnterLog> parkCarEnterLogs = enterLogList.stream()
                .sorted(Comparator.comparing(ParkCarEnterLog::getCarEnterTime))
                .collect(Collectors.toList());
        return parkCarEnterLogs;
    }

}
